/**
 * @file route
 * @author shenli
 */

var methods = require('methods');
var flatten = require('array-flatten');
var Layer = require('./layer');

var slice = Array.prototype.slice;
var toString = Object.prototype.toString;

function Route(path) {
    this.path = path;
    this.stack = [];
    this.methods = {};
}

/**
 * Determine if the route handles a given method.
 *
 * @param {string} method method name
 * @return {boolean}
 */
Route.prototype.handleMethod = function (method) {
    if (this.methods._all) {
        return true;
    }

    var name = method.toLowerCase();

    if (name === 'head' && !this.methods.head) {
        name = 'get';
    }

    return !!this.methods[name];
};

Route.prototype.dispath = function (req, res, done) {
    var index = 0;
    var stack = this.stack;
    if (stack.length === 0) {
        return done();
    }

    var method = req.method.toLowerCase();

    req.route = this;

    next();

    function next(err) {
        if (err && err === 'route') {
            return done();
        }

        var layer = stack[index++];

        if (!layer) {
            return done(err);
        }

        if (layer.method && layer.method !== method) {
            return next(err);
        }

        if (err) {
            layer.handleError(err, req, res, next);
        }
        else {
            layer.handleRequest(req, res, next);
        }
    }
};


methods.forEach(function (method) {
    Route.prototype[method] = function () {
        var handles = flatten(slice.call(arguments));
        for (var i = 0; i < handles.length; i++) {
            var handle = handles[i];

            if (typeof handle !== 'function') {
                var type = toString.call(handle);
                var msg = 'Route.' + method + '() requires callback functions but got a ' + type;
                throw new Error(msg);
            }

            var layer = Layer('/', {}, handle);
            layer.method = method;

            this.methods[method] = true;
            this.stack.push(layer);
        }
    };
});



module.exports = Route;
